package org.phalanx.servlet.webmessages;

import java.util.ArrayList;
import java.util.Iterator;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.phalanx.game.units.VillageUnit;
import org.phalanx.map.MapCoordinates;
import org.phalanx.server.PhalanxServer;
import org.phalanx.server.ServerCache.CacheManager;
import org.phalanx.server.game.GameState;
import org.phalanx.server.game.PhalanxBattleRPGEngine;
import org.phalanx.server.game.PhalanxGameStateMessage;
import org.phalanx.server.game.PhalanxUnitState;
import org.phalanx.server.user.PhalanxUser;
import org.phalanx.servlet.websession.ServletAuthenticatorManager;
import org.phalanx.servlet.websession.UserWebSession;

public class PhalanxGameStateContext implements WebMessageable {
	private ArrayList<PhalanxUnitState> playerGameState;
	private ArrayList<MapCoordinates> fieldOfVision;
	private PhalanxServer pServer;
	
	public static final String CONTEXT = "gamestate";
	
	public PhalanxGameStateContext(PhalanxServer pServer){
		playerGameState = new ArrayList<PhalanxUnitState>();
		fieldOfVision = new ArrayList<MapCoordinates>();
		this.pServer = pServer;
	}
	
	@Override
	public void onContextLoadable(String context, Cookie authCookie,
			HttpServletRequest req, HttpServletResponse resp) {
		if (context.equals(CONTEXT)){
			ServletAuthenticatorManager s = new ServletAuthenticatorManager(pServer);

			if (authCookie != null && s.authenticate(authCookie) != null){
				String gameId = req.getParameter("gameid");
				String turnId = req.getParameter("turnid");
				
				PhalanxUser u = (PhalanxUser)pServer.getCacheManager().getElement("TokenSessionCache", authCookie.getValue());
				
				if (u != null){
					UserWebSession session = (UserWebSession)pServer.getCacheManager().getElement("UserWebFeedCache", u.getId());

					if (session != null){
						session.sendMessage(getGameStateMessage(Integer.valueOf(gameId), 
								Integer.valueOf(turnId), u.getId()));
					}
				}
			}
		}

	}
	
	private PhalanxGameStateMessage getGameStateMessage(Integer gameId, Integer turnId, Integer uId){
		PhalanxGameStateMessage pMsg = new PhalanxGameStateMessage();
		CacheManager cacheMgr = pServer.getCacheManager();
		
		pMsg.setTurn(turnId);
		pMsg.setUserId(uId);
		pMsg.setGameId(gameId);
		
		// Get Field of Vision
		
		PhalanxBattleRPGEngine rpgEngine = (PhalanxBattleRPGEngine)cacheMgr.getElement("GameEngineCache", gameId);
		
		if (rpgEngine != null){
			fieldOfVision = rpgEngine.getTotalFieldOfVision(uId, turnId);
		}
		
		// Get unit state of all user's units
		
		GameState gState = (GameState)cacheMgr.getElement("CurrentGameState", gameId);
		
		Iterator<PhalanxUnitState> i = gState.getUnitStateForCurrentTurn(turnId).iterator();
		
		while(i.hasNext()){
			PhalanxUnitState oneUnit = i.next();
			
			if (oneUnit.getUserId().equals(uId)){
				addToPlayerGameState(oneUnit);
			} else if (getIsVisible(oneUnit.getMapCoordinates())){ // Not ours but we can see it
				addToPlayerGameState(oneUnit);
			} else if (oneUnit.getPhalanxUnit().equals(new VillageUnit().getUnitName())){
				addToPlayerGameState(oneUnit);
			}
		}
		
		pMsg.setFieldOfVision(fieldOfVision);
		pMsg.setUserGameState(playerGameState);
		
		return pMsg;
	}
	
	private void addToPlayerGameState(PhalanxUnitState uState){
		if (!playerGameState.contains(uState)){
			playerGameState.add(uState);
		}
	}
	
	private boolean getIsVisible(MapCoordinates c){
		boolean isVisible = false;
		
		Iterator<MapCoordinates> i = fieldOfVision.iterator();
		
		while(i.hasNext() && !isVisible){
			MapCoordinates newCoor = i.next();
			isVisible = newCoor.equals(c);
		}
		
		return isVisible;
	}

}
